﻿using Infrastructure;
using Infrastructure.Attribute;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using ZR.DataCollection.Model;
using ZR.DataCollection.OperationCore.AbstractFactory;
using ZR.DataCollection.OperationCore.OperationEnum;
using ZR.DataCollection.OperationCore.OperationHelper;
using ZR.DataCollection.SingleParameter;
using ZR.Model.Models.ProductionControl;
using ZR.Service.Business.IBusinessService;
using ZR.Service.IService.ProductionControl;

namespace ZR.DataCollection.OperationCore.OperationMode
{
    /// <summary>
    /// 扫码（PLC请求）
    /// </summary>
    public sealed class ScanCode : OperationInfoBase
    {
        public override event Action<string> Event_Notification;

        private bool collectStatus = true;
        private readonly IMaterialRuleConfigService _materialRuleConfigService = App.GetRequiredService<IMaterialRuleConfigService>();
        private readonly IScanInfoService _scanInfoService = App.GetRequiredService<IScanInfoService>();
        private readonly IWorkstationConfigService _workstationConfigService = App.GetRequiredService<IWorkstationConfigService>();

        public ScanCode(int operationType, string stationType) : base(operationType, stationType)
        {
        }

        public override void WorkDetail(ImpParameter imp)
        {
            //设置当前工站开始时间
            ProductInfoManager.Instance.SetStartTime(_stationType, DateTime.Now);
            DataDock dataDock = imp.objectParam as DataDock;
            var keyValuePairs = CurrentCruxPoint(dataDock.LineCode, dataDock.ProductType, dataDock.ItemNo);
            SpotHandle(imp, keyValuePairs);
        }

        public override void SpotHandle(ImpParameter parameter, Dictionary<int, List<OperationPointConfig>> SpotGroup)
        {
            foreach (var SpotInfo in SpotGroup)
            {
                switch (SpotInfo.Key)
                {
                    case (int)DataOperateEnum.Read:
                        ReadFunction(parameter, SpotInfo.Value);
                        break;

                    case (int)DataOperateEnum.Write:
                        SpotInfo.Value.ForEach(x =>
                        {
                            if (!collectStatus && x.ItemSort.Equals(3))
                            {
                                parameter.PLCDetail.WriteValue(x.ItemNo, x.ItemWriteValue);
                            }
                            parameter.PLCDetail.WriteValue(x.ItemNo, x.ItemWriteValue);
                        });
                        break;

                    case (int)DataOperateEnum.Verify:
                        break;

                    default:
                        break;
                }
            }
        }

        private void ReadFunction(ImpParameter parameter, List<OperationPointConfig> OperationPointList)
        {
            DataDock? dataDock = parameter.objectParam as DataDock;
            foreach (var PointInfo in OperationPointList)
            {
                string readCode = (string)parameter.PLCDetail.ReadValue(PointInfo.ItemNo);
                if (string.IsNullOrWhiteSpace(readCode))
                {
                    collectStatus = false;
                    return;
                }
                bool mve = _workstationConfigService.QueryInfo(dataDock.LineCode, dataDock.StationCode).MaterialVerificationEnabled;
                MaterialRuleConfig materialRuleInfo = null;
                if (mve)
                {
                    materialRuleInfo = _materialRuleConfigService.QueryByClause(qbc =>
                  readCode.StartsWith(qbc.MaterialCode)
                  && qbc.LineCode.Equals(dataDock.LineCode)
                  && qbc.StationCode.Equals(dataDock.StationCode)
                  && qbc.OrderCode.Equals(dataDock.OrderCode));
                    if (materialRuleInfo == null)
                    {
                        collectStatus = false;
                        break;
                    }
                }

                ScanInfo scanInfo = new ScanInfo()
                {
                    LineCode = dataDock.LineCode,
                    StationCode = dataDock.StationCode,
                    OrderCode = dataDock.OrderCode,
                    ProductId = dataDock.ProductCode,
                    ProductType = dataDock.ProductType,
                    MaterialName = materialRuleInfo?.MaterialName,
                    MaterialCode = materialRuleInfo?.MaterialCode,
                    MaterialSn = readCode
                };
                _scanInfoService.InsertAsync(scanInfo);
            }
        }
    }
}